package czy.demo.config;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import org.springframework.cache.support.NullValue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

import java.io.IOException;

/* Jackson配置 */
@Configuration
public class JacksonConfig {

    /* class序列化器，用于记录实体类名 */
    private static final class ClassSerializer extends StdSerializer<NullValue>{

        private final String classIdentifier;

        ClassSerializer(@Nullable String classIdentifier) {

            super(NullValue.class);
            this.classIdentifier = StringUtils.hasText(classIdentifier) ? classIdentifier : "@class";
        }

        @Override
        public void serialize(NullValue value, JsonGenerator jgen, SerializerProvider provider)
                throws IOException {

            jgen.writeStartObject();
            jgen.writeStringField(classIdentifier, NullValue.class.getName());
            jgen.writeEndObject();
        }
    }


    /* 手动配置ObjectMapper */
    @Bean
    @Primary
    public ObjectMapper objectMapper(){

        /* 添加了hibernate5插件的jackson对象，防止getter方法触发数据获取 */
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder().modulesToInstall(new Hibernate5Module());
        ObjectMapper mapper = builder.build();

        /* 注册redis序列化器 */
        mapper.registerModule(new SimpleModule().addSerializer(new ClassSerializer(null)));
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        return mapper;
    }

}
